package com.atguigu.lease.admin.service.impl;

import com.atguigu.lease.admin.mapper.ApartmentFacilityMapper;
import com.atguigu.lease.admin.mapper.ApartmentFeeValueMapper;
import com.atguigu.lease.admin.mapper.ApartmentLabelMapper;
import com.atguigu.lease.admin.service.*;
import com.atguigu.lease.model.bean.*;
import com.atguigu.lease.model.enums.ItemTypeEnum;
import com.atguigu.lease.model.vo.*;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
//import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.atguigu.lease.admin.mapper.ApartmentInfoMapper;
import org.checkerframework.checker.units.qual.A;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
* @author 1
* @description 针对表【apartment_info(公寓信息表)】的数据库操作Service实现
* @createDate 2025-06-20 14:04:43
*/
@Service
public class ApartmentInfoServiceImpl extends ServiceImpl<ApartmentInfoMapper, ApartmentInfo>
    implements ApartmentInfoService{
    @Autowired
    private ProvinceInfoService provinceInfoService;
    @Autowired
    private CityInfoService cityInfoService;
    @Autowired
    private DistrictInfoService districtInfoService;
    @Autowired
    private ApartmentFacilityService apartmentFacilityService;
    @Autowired
    private ApartmentLabelService apartmentLabelService;
    @Autowired
    private ApartmentFeeValueService apartmentFeeValueService;
    @Autowired
    private GraphInfoService graphInfoService;

    @Autowired
    private ApartmentFacilityMapper apartmentFacilityMapper;
    @Autowired
    private ApartmentLabelMapper apartmentLabelMapper;
    @Autowired
    private ApartmentFeeValueMapper apartmentFeeValueMapper;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void saveOrUpdateApartmentSubmitVo(ApartmentSubmitVo apartmentSubmitVo) {
        //1、先保存或更新公寓: 得到公寓的id
        // 更新前端会提交公寓的id
        boolean isUpdate = apartmentSubmitVo.getId()!=null; //判断是不是更新 true表示更新 false表示新增
        //前端未提交省市区名称：
        ProvinceInfo provinceInfo = provinceInfoService.getById(apartmentSubmitVo.getProvinceId());
        CityInfo cityInfo = cityInfoService.getById(apartmentSubmitVo.getCityId());
        DistrictInfo districtInfo = districtInfoService.getById(apartmentSubmitVo.getDistrictId());
        apartmentSubmitVo.setProvinceName(provinceInfo.getName());
        apartmentSubmitVo.setCityName(cityInfo.getName());
        apartmentSubmitVo.setDistrictName(districtInfo.getName());
        //调用mp的通用service 保存或更新 公寓表中的数据
        this.saveOrUpdate(apartmentSubmitVo);
        Long id = apartmentSubmitVo.getId();//获取公寓id
        //2、再保存或更新公寓的其他信息: 使用公寓的id关联数据
        // 如果新增公寓： 所有的配套、标签等数据都是第一次添加  直接保存
        // 如果更新公寓： 有些配套 标签数据是新增的，有些是已存在的，还有一些没有传入的 但是数据库还保存着
        //              可以先删除所有的配套标签数据，然后将更新的配套 标签等数据新增到表中
        //2.1 更新：先删除公寓的其他信息
        if(isUpdate){
            //配套: 使用公寓id删除公寓的所有配套
            apartmentFacilityService.remove(Wrappers.lambdaQuery(ApartmentFacility.class)
                    .eq(ApartmentFacility::getApartmentId, id));
            //标签
            apartmentLabelService.remove(Wrappers.lambdaQuery(ApartmentLabel.class)
                    .eq(ApartmentLabel::getApartmentId, id));
            //杂费值
            apartmentFeeValueService.remove(Wrappers.lambdaQuery(ApartmentFeeValue.class)
                    .eq(ApartmentFeeValue::getApartmentId, id));

            //图片: 图片表包含了公寓和房间的图片(公寓表 和房间表的id都使用了自增长，所以id可能重复)
            // item_id=公寓id and item_type=1(公寓类型)
            // delete from graph_info where item_type = 1 and item_id = #{apartmentId} and is_deleted = 0
            graphInfoService.remove(Wrappers.lambdaQuery(GraphInfo.class)
                    .eq(GraphInfo::getItemType , ItemTypeEnum.APARTMENT)
                    .eq(GraphInfo::getItemId, id));
        }
        //2.2 新增或者更新：  保存公寓的其他信息
        // 》1-配套信息
        List<Long> facilityInfoIds = apartmentSubmitVo.getFacilityInfoIds();
//        apartmentSubmitVo.getFacilityInfoIds()
//                .stream()
                // 将Long-> ApartmentFacility
        //公寓配套集合
        List<ApartmentFacility> apartmentFacilities = new ArrayList<>();
        facilityInfoIds.forEach(facilityId->{
            //公寓配套对象： 由公寓id和配套id组成
            ApartmentFacility apartmentFacility = new ApartmentFacility();
            apartmentFacility.setApartmentId(id);
            apartmentFacility.setFacilityId(facilityId);
            //遍历创建的一个公寓配套对象 存到集合中
            apartmentFacilities.add(apartmentFacility);
        });
        // 批量保存公寓配套对象集合(List<ApartmentFacility>  [{"apartmentId":1 , facilityId:1 }])
        // insert into apartment_facility(apartment_id ,facility_id) values(1,2),(1,3),(1,4)
        apartmentFacilityService.saveBatch(apartmentFacilities);

        // 》-2标签信息
        List<ApartmentLabel> apartmentLabels = apartmentSubmitVo.getLabelIds().stream()
                //streamAPI map()可以将流中的每个元素转为其他类型的对象
                .map(labelId -> {
                    ApartmentLabel apartmentLabel = new ApartmentLabel();
                    // 设置公寓id
                    apartmentLabel.setApartmentId(id);
                    // 设置公寓选择的标签id
                    apartmentLabel.setLabelId(labelId);
                    return apartmentLabel;
                })
                // 将前面的流数据转为对象 存到List集合中
                .collect(Collectors.toList());
        //批量保存
        apartmentLabelService.saveBatch(apartmentLabels);

        // 》3-杂费值信息
        //将杂费值id列表转为  公寓杂费值对象集合
        List<ApartmentFeeValue> apartmentFeeValues = apartmentSubmitVo.getFeeValueIds().stream()
                .map(feeValueId -> {
                    ApartmentFeeValue apartmentFeeValue = new ApartmentFeeValue();
                    apartmentFeeValue.setApartmentId(id);
                    apartmentFeeValue.setFeeValueId(feeValueId);
                    return apartmentFeeValue;
                }).collect(Collectors.toList());

        //批量保存
        apartmentFeeValueService.saveBatch(apartmentFeeValues);
        // >4-图片
        //  将接受到的图片集合  转为数据库表映射的实体类对象集合(还需要绑定公寓+设置图片的类型)
        List<GraphInfo> graphInfos = apartmentSubmitVo.getGraphVoList().stream()
                .map(graphVo -> {
                    GraphInfo graphInfo = new GraphInfo();
                    graphInfo.setUrl(graphVo.getUrl());
                    graphInfo.setName(graphVo.getName());
                    // 设置图片属于哪个公寓
                    graphInfo.setItemId(id);
                    // 设置图片的类型：1-公寓  2-房间
                    graphInfo.setItemType(ItemTypeEnum.APARTMENT.getCode());
                    return graphInfo;
                }).collect(Collectors.toList());
        graphInfoService.saveBatch(graphInfos);

    }

    @Override
    public Page<ApartmentItemVo> getPageItem(Long current, Long size, ApartmentQueryVo queryVo) {
        //mp自定义分页：
        // 1、配置分页拦截器 2、传入page对象携带分页的页码和size  3、传入自定义条件 手动解析在sql中使用
        return baseMapper.selectApartmentItemVoPage(new Page<>(current,size) ,queryVo);
    }

    @Override
    public ApartmentDetailVo getDetailById(Long id) {
        ApartmentDetailVo apartmentDetailVo = new ApartmentDetailVo();
        //1、查询公寓数据
        ApartmentInfo apartmentInfo = this.getById(id);
        //设置公寓属性值给vo
        // BeanUtils 是spring的工具类，可以将一个对象的属性值拷贝给另一个对象相同类型相同名称的属性！
        BeanUtils.copyProperties(apartmentInfo, apartmentDetailVo); //尽量早复制！
        //2、查询其他数据设置给vo
        //2.1 查询公寓的配套数据：  需要通过中间表联查(apratment_facility    facility_info表)
        List<FacilityInfo> facilityInfos = apartmentFacilityMapper
                .selectFacilityInfosByApartmentId(id);

        //设置配套列表给Vo
        apartmentDetailVo.setFacilityInfoList(facilityInfos);
        //2.2 查询公寓的标签数据：
        List<LabelInfo> labelInfos = apartmentLabelMapper.selectLabelInfsByApartmentId(id);

        apartmentDetailVo.setLabelInfoList(labelInfos);
        //2.3 查询公寓的杂费值数据：
        List<FeeValueVo> feeValueVos =apartmentFeeValueMapper.selectFeeValueVosByApartmentId(id);

        apartmentDetailVo.setFeeValueVoList(feeValueVos);
        //2.4 查询公寓的图片数据：
        // graph_info表：  使用了item_id 关联公寓id
        // 使用公寓id+ 图片所属类型 查询公寓的图片列表
        List<GraphVo> graphVoList = graphInfoService.list(Wrappers.lambdaQuery(GraphInfo.class)
                        .eq(GraphInfo::getItemType, ItemTypeEnum.APARTMENT)
                        .eq(GraphInfo::getItemId, id))
                .stream()
                .map(graphInfo -> {
                    GraphVo graphVo = new GraphVo();
//                    graphVo.setName(graphInfo.getName());
//                    graphVo.setUrl(graphInfo.getUrl());
                    BeanUtils.copyProperties(graphInfo, graphVo);
                    return graphVo;
                }).collect(Collectors.toList());
        apartmentDetailVo.setGraphVoList(graphVoList);
        //最终：将组装好数据的vo对象返回
        return apartmentDetailVo;
    }
    @Transactional(rollbackFor = Exception.class) //启用声明式事务
    @Override
    public void deleteApartmentById(Long id) {
        //1、删除公寓数据
        this.removeById(id);
        //2、删除公寓配套数据
        apartmentFacilityService.remove(Wrappers.lambdaQuery(ApartmentFacility.class)
                .eq(ApartmentFacility::getApartmentId, id));
        //3、删除公寓标签数据
        apartmentLabelService.remove(Wrappers.lambdaQuery(ApartmentLabel.class)
                .eq(ApartmentLabel::getApartmentId, id));
        //4、删除公寓杂费值数据
        apartmentFeeValueService.remove(Wrappers.lambdaQuery(ApartmentFeeValue.class)
                .eq(ApartmentFeeValue::getApartmentId, id));
        //5、删除图片数据
        graphInfoService.remove(Wrappers.lambdaQuery(GraphInfo.class)
                .eq(GraphInfo::getItemType, ItemTypeEnum.APARTMENT)
                .eq(GraphInfo::getItemId, id));
    }
}




